home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / libz / timemk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-23  |  4.4 KB  |  161 lines

  1. #
  2.  
  3. /*LINTLIBRARY*/
  4.  
  5. #ifndef lint
  6. #ifndef NOID
  7. static char    sccsid[] = "@(#)timemk.c    3.2";
  8. #endif /* !NOID */
  9. #endif /* !lint */
  10.  
  11. #ifdef STD_INSPIRED
  12.  
  13. /*
  14. ** Code provided by Robert Elz, who writes:
  15. **    The "best" way to do mktime I think is based on an idea of Bob
  16. **    Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
  17. **    It does a binary search of the time_t space.  Since time_t's are
  18. **    just 32 bits, its a max of 32 iterations (even at 64 bits it
  19. **    would still be very reasonable).
  20. **
  21. ** This code does handle "out of bounds" values in the way described
  22. ** for "mktime" in the October, 1986 draft of the proposed ANSI C Standard;
  23. ** though this is an accident of the implementation and *cannot* be made to
  24. ** work correctly for the purposes there described.
  25. **
  26. ** A warning applies if you try to use these functions with a version of
  27. ** "localtime" that has overflow problems (such as System V Release 2.0
  28. ** or 4.3 BSD localtime).
  29. ** If you're not using GMT and feed a value to localtime
  30. ** that's near the minimum (or maximum) possible time_t value, localtime
  31. ** may return a struct that represents a time near the maximum (or minimum)
  32. ** possible time_t value (because of overflow).  If such a returned struct tm
  33. ** is fed to timelocal, it will not return the value originally feed to
  34. ** localtime.
  35. */
  36.  
  37. #include "time.h"
  38. #include "tzfile.h"
  39. #include "sys/types.h"
  40.  
  41. #ifndef WRONG
  42. #define WRONG    (-1)
  43. #endif /* !WRONG */
  44.  
  45. extern struct tm *    localtime();
  46. extern struct tm *    gmtime();
  47. extern struct tm *    offtime();
  48.  
  49. static time_t
  50. timemk(timeptr, funcp, offset)
  51. struct tm *    timeptr;
  52. struct tm * (*    funcp)();
  53. long        offset;
  54. {
  55.     register int    direction;
  56.     register int    bits;
  57.     time_t        t;
  58.     struct tm    yourtm, mytm;
  59.  
  60.     yourtm = *timeptr;
  61.     /*
  62.     ** Correct the tm supplied, in case some of its values are
  63.     ** out of range.
  64.     */
  65.     while (yourtm.tm_sec >= SECS_PER_MIN)
  66.         ++yourtm.tm_min, yourtm.tm_sec -= SECS_PER_MIN;
  67.     while (yourtm.tm_sec < 0)
  68.         --yourtm.tm_min, yourtm.tm_sec += SECS_PER_MIN;
  69.     while (yourtm.tm_min >= MINS_PER_HOUR)
  70.         ++yourtm.tm_hour, yourtm.tm_min -= MINS_PER_HOUR;
  71.     while (yourtm.tm_min < 0)
  72.         --yourtm.tm_hour, yourtm.tm_min += MINS_PER_HOUR;
  73.     while (yourtm.tm_hour >= HOURS_PER_DAY)
  74.         ++yourtm.tm_mday, yourtm.tm_hour -= HOURS_PER_DAY;
  75.     while (yourtm.tm_hour < 0)
  76.         --yourtm.tm_mday, yourtm.tm_hour += HOURS_PER_DAY;
  77.     while (yourtm.tm_mday > 31)        /* trust me [kre] */
  78.         ++yourtm.tm_mon, yourtm.tm_mday -= 31;
  79.     while (yourtm.tm_mday <= 0)
  80.         --yourtm.tm_mon, yourtm.tm_mday += 31;
  81.     while (yourtm.tm_mon >= MONS_PER_YEAR)
  82.         ++yourtm.tm_year, yourtm.tm_mon -= MONS_PER_YEAR;
  83.     while (yourtm.tm_mon < 0)
  84.         --yourtm.tm_year, yourtm.tm_mon += MONS_PER_YEAR;
  85.     /*
  86.     ** Calcluate the number of magnitude bits in a time_t
  87.     ** (this works regardless of whether time_t is
  88.     ** signed or unsigned, though lint complains if unsigned).
  89.     */
  90.     for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
  91.         ;
  92.     /*
  93.     ** If time_t is signed, then 0 is the median value,
  94.     ** if time_t is unsigned, then 1 << bits is median.
  95.     */
  96.     t = (t < 0) ? 0 : ((time_t) 1 << bits);
  97.     for ( ; ; ) {
  98.         mytm = (funcp == offtime) ?
  99.             *((*funcp)(&t, offset)) : *((*funcp)(&t));
  100.         if ((direction = (mytm.tm_year - yourtm.tm_year)) == 0 &&
  101.             (direction = (mytm.tm_mon - yourtm.tm_mon)) == 0 &&
  102.             (direction = (mytm.tm_mday - yourtm.tm_mday)) == 0 &&
  103.             (direction = (mytm.tm_hour - yourtm.tm_hour)) == 0 &&
  104.             (direction = (mytm.tm_min - yourtm.tm_min)) == 0)
  105.                 direction = mytm.tm_sec - yourtm.tm_sec;
  106.         if (direction == 0) {
  107.             *timeptr = mytm;
  108.             return t;
  109.         }
  110.         if (bits-- < 0) {
  111.             *timeptr = yourtm;    /* restore "original" value */
  112.             if (yourtm.tm_mday == 31) {
  113.                 timeptr->tm_mday = 1;
  114.                 ++(timeptr->tm_mon);
  115.                 t = timemk(timeptr, funcp, offset);
  116.                 if (t != WRONG)
  117.                     return t;
  118.                 *timeptr = yourtm;
  119.             } else if (yourtm.tm_mon == TM_FEBRUARY &&
  120.                 yourtm.tm_mday > 28) {
  121.                     timeptr->tm_mday -= 28;
  122.                     ++(timeptr->tm_mon);
  123.                     t = timemk(timeptr, funcp, offset);
  124.                     if (t != WRONG)
  125.                         return t;
  126.                     *timeptr = yourtm;
  127.             }
  128.             return WRONG;
  129.         }
  130.         if (bits < 0)
  131.             --t;
  132.         else if (direction > 0)
  133.             t -= (time_t) 1 << bits;
  134.         else    t += (time_t) 1 << bits;
  135.     }
  136. }
  137.  
  138. time_t
  139. timelocal(timeptr)
  140. struct tm *    timeptr;
  141. {
  142.     return timemk(timeptr, localtime, 0L);
  143. }
  144.  
  145. time_t
  146. timegm(timeptr)
  147. struct tm *    timeptr;
  148. {
  149.     return timemk(timeptr, gmtime, 0L);
  150. }
  151.  
  152. time_t
  153. timeoff(timeptr, offset)
  154. struct tm *    timeptr;
  155. long        offset;
  156. {
  157.     return timemk(timeptr, offtime, offset);
  158. }
  159.  
  160. #endif /* STD_INSPIRED */
  161.